package com.shf.log;

import com.shf.entity.Syslog;
import com.shf.mapper.SyslogMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.UUID;

/**
 * 日志切面类
 * @author 叶枫
 */
@Component
@Aspect
public class LogAop {
    @Autowired
    private HttpServletRequest req;
    @Autowired
    private SyslogMapper syslogMapper;

    private Syslog syslog;

    private Date visitTime;

   private Method method = null;


    /**
     * 前置通知
     * @param jp
     */
    @Before("execution(* com.shf.controller.*.*(..))")
    public void before(JoinPoint jp){
        //记录访问时间
        visitTime = new Date();
        //获取当前切入的controller类的反射对象
        Class<?> aClass = jp.getTarget().getClass();

        //获取要访问的方法名称
        MethodSignature ms = (MethodSignature)jp.getSignature();
        method = ms.getMethod();
//        //获取要访问方法的参数
//        Object[] args = jp.getArgs();
//        System.out.println(Arrays.toString(args));


//        //获取具体执行的方法的Method对象
//        if (args == null || args.length == 0){
//            try {
//                //只能获取无参的方法对象
//                method = aClass.getMethod(methodName);
//            } catch (NoSuchMethodException e) {
//                throw new RuntimeException(e);
//            }
//        }else {
//            Class[] classArgs = new Class[args.length];
//            for (int i = 0; i < args.length; i++) {
//                Object arg = args[i];
//
//                classArgs[i] = arg.getClass();
//            }
//
//            //Method对象
//            try {
//                 method = aClass.getMethod(methodName, classArgs);
//            } catch (NoSuchMethodException e) {
//                throw new RuntimeException(e);
//            }
//        }

        String url = "";
        //获取url
        System.out.println(method);
        if (aClass != null && method != null && aClass != LogAop.class){
            //获取类上的 @requestMapping()的路径
            RequestMapping classAnnotation = (RequestMapping) aClass.getAnnotation(RequestMapping.class);
            if (classAnnotation.value() != null){
                //父路径
                 String [] path = classAnnotation.value();
                //获取方法上的@requestMapping()的路径
                RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
                if (methodAnnotation != null){
                    //子路径
                    String []gp = methodAnnotation.value();
                    url = path[0] + gp[0];

                    //获取访问ip
                    String ip = req.getRemoteAddr();
                    ip = ip.equals("0:0:0:0:0:0:0:1") ?"127.0.0.1":ip;

                    //获取当前用户
                    SecurityContext context = SecurityContextHolder.getContext();
                    User user = (User)context.getAuthentication().getPrincipal();

                    String username = user.getUsername();

                    syslog = new Syslog();

                    syslog.setId(UUID.randomUUID().toString());
                    System.out.println(syslog.getId());
                    syslog.setUrl(url);
                    syslog.setMethod(aClass.getName() + method.getName());
                    syslog.setUsername(username);
                    syslog.setIp(ip);

                    syslog.setVisitTime(visitTime);

                }


            }



        }




    }

    /**
     * 后置通知
     * @param jp
     */
    @After("execution(* com.shf.controller.*.*(..))")
    public void after(JoinPoint jp){


        long executionTime = System.currentTimeMillis() - syslog.getVisitTime().getTime();
        syslog.setExecutionTime(executionTime);

        syslogMapper.saveLog(syslog);

    }
}
